package co.yixiang.service.impl;

import co.yixiang.domain.KryConfig;
import co.yixiang.repository.KryConfigRepository;
import co.yixiang.service.KryConfigService;
import co.yixiang.service.dto.OrderQueryCriteia;
import co.yixiang.service.dto.RefundApplyCriteia;
import co.yixiang.service.dto.ScanCodePay;
import co.yixiang.utils.GuestUtils;
import co.yixiang.utils.HttpsUtil;
import co.yixiang.utils.OrderUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;

/**客如云接口服务
 * @author frq
 * @date 2020-07-27
 */
@Slf4j
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class KryConfigServiceImpl implements KryConfigService {
    @Autowired
    private KryConfigRepository kryConfigRepository;

    @Override
    public KryConfig find() {
        Optional<KryConfig> kryConfig = kryConfigRepository.findById(1);
        return kryConfig.orElseGet(KryConfig::new);
    }

    /**
     * 扫码支付(主扫获取二维码链接)
     * @param scanCodePay 门店参数
     * @return
     */
    @Override
    public Map<String, Object> scanCode(ScanCodePay scanCodePay) {
        KryConfig kryConfig=find();
        Map<String, Object> map = new HashMap<>();
        map.put("status", "0");
        String accessUrl = null;
        try {
            accessUrl = getUrl(kryConfig, "/open/v1/wallet/scanCode");
        } catch (NoSuchAlgorithmException e) {
            log.error("生成签名异常，请联系管理员!" + e.toString());
            map.put("status", "1");
            map.put("errorMsg", "生成签名异常，请联系管理员!");
            return map;
        }
        try {
            String pushParams = JSONObject.toJSONString(scanCodePay);
            log.info("扫码支付请求url:"+accessUrl);
            log.info("扫码支付请求参数:"+pushParams);
            //发送请求
            String result = HttpsUtil.post(accessUrl, pushParams);
            log.info("扫码支付返回参数:"+result);
//            JSONObject obj = JSONObject.parseObject(result);
            map.put("resultParams", result);
        } catch (Exception e) {
            log.error("主扫获取二维码异常，请联系管理员!" + e.toString());
            map.put("status", "1");
            map.put("errorMsg", "主扫获取二维码异常，请联系管理员!");
            return map;
        }
        return map;
    }
    /**
     * 查询支付结果
     * @param outTradeNo 支付单号
     * @return
     */
    @Override
    public Map<String, Object> payQuery(String  outTradeNo) {
        KryConfig kryConfig=find();
        Map<String, Object> map = new HashMap<>();
        map.put("status", "0");
        String accessUrl = null;
        try {
            accessUrl = getUrl(kryConfig, "/open/v1/wallet/payQuery");
        } catch (NoSuchAlgorithmException e) {
            log.error("生成签名异常，请联系管理员!" + e.toString());
            map.put("status", "1");
            map.put("errorMsg", "生成签名异常，请联系管理员!");
            return map;
        }
        Map<String,String> mapParams=new HashMap<>();
        mapParams.put("outTradeNo",outTradeNo);
        try {
            String pushParams = JSONObject.toJSONString(mapParams);
            log.info("查询支付结果请求url:"+accessUrl);
            log.info("查询支付结果请求参数:"+pushParams);
            //发送请求
            String result = HttpsUtil.post(accessUrl, pushParams);
            log.info("查询支付结果返回参数:"+result);
//            JSONObject obj = JSONObject.parseObject(result);
            map.put("resultParams", result);
        } catch (Exception e) {
            log.error("查询支付结果异常，请联系管理员!" + e.toString());
            map.put("status", "1");
            map.put("errorMsg", "查询支付结果异常，请联系管理员!");
            return map;
        }
        return map;
    }

    /**
     * 查询订单列表
     * @param criteia
     * @return
     */
    @Override
    public Map<String, Object> orderList(OrderQueryCriteia criteia){
        KryConfig kryConfig=find();
        Map<String, Object> map = new HashMap<>();
        map.put("status", "0");
        String accessUrl = null;
        try {
            accessUrl = getUrl(kryConfig, "/open/v1/data/order/export2");
        } catch (NoSuchAlgorithmException e) {
            log.error("生成签名异常，请联系管理员!" + e.toString());
            map.put("status", "1");
            map.put("errorMsg", "生成签名异常，请联系管理员!");
            return map;
        }
        try {
            String pushParams = JSONObject.toJSONString(criteia);
            log.info("查询订单列表请求url:"+accessUrl);
            log.info("查询订单列表请求参数:"+pushParams);
            //发送请求
            String result = HttpsUtil.post(accessUrl, pushParams);
            log.info("查询订单列表返回参数:"+result);
//            JSONObject obj = JSONObject.parseObject(result);
            map.put("resultParams", result);
        } catch (Exception e) {
            log.error("查询订单列表异常，请联系管理员!" + e.toString());
            map.put("status", "1");
            map.put("errorMsg", "查询订单列表异常，请联系管理员!");
            return map;
        }
        return map;
    }
    /**
     * 拼接请求URL
     *
     * @param kryConfig
     * @return
     */
    @Override
    public String getUrl(KryConfig kryConfig, String methods) throws NoSuchAlgorithmException {
        Map<String, Object> params = new LinkedHashMap<>();
        params.put("appKey", kryConfig.getAppKey());
        params.put("shopIdenty", kryConfig.getShopIdenty());
        params.put("timestamp", OrderUtil.getSecondTimestampTwo());
        params.put("version", "1.0");
        StringBuilder sortedParams = new StringBuilder();
        params.entrySet().stream().forEachOrdered(paramEntry -> sortedParams.append(paramEntry.getKey()).append(paramEntry.getValue()));
        sortedParams.append(kryConfig.getToken());
        //生成签名
        String sign = GuestUtils.getSign(sortedParams.toString());
        params.put("sign", sign);
        // 拼接URL
        String url = HttpsUtil.spellUrl(kryConfig.getDomain() + methods, params);
        return url;
    }

    /**
     * 退款申请
     * @param criteia
     * @return
     */
    @Override
    public Map<String, Object> refundApply(RefundApplyCriteia criteia) {
        KryConfig kryConfig=find();
        Map<String, Object> map = new HashMap<>();
        map.put("status", "0");
        String accessUrl = null;
        try {
            accessUrl = getUrl(kryConfig, "/open/v1/wallet/refundApply");
        } catch (NoSuchAlgorithmException e) {
            log.error("生成签名异常，请联系管理员!" + e.toString());
            map.put("status", "1");
            map.put("errorMsg", "生成签名异常，请联系管理员!");
            return map;
        }
        try {
            String pushParams = JSONObject.toJSONString(criteia);
            log.info("退款申请请求url:"+accessUrl);
            log.info("退款申请请求参数:"+pushParams);
            //发送请求
            String result = HttpsUtil.post(accessUrl, pushParams);
            log.info("退款申请返回参数:"+result);
//            JSONObject obj = JSONObject.parseObject(result);
            map.put("resultParams", result);
        } catch (Exception e) {
            log.error("退款申请异常，请联系管理员!" + e.toString());
            map.put("status", "1");
            map.put("errorMsg", "退款申请异常，请联系管理员!");
            return map;
        }
        return map;
    }
    /**
     * 退款状态查询
     * @param outRefundNo 调用方退款单号
     * @return outTradeNo 支付单号
     */
    @Override
    public Map<String, Object> refundQuery(String outRefundNo, String outTradeNo) {
        KryConfig kryConfig=find();
        Map<String, Object> map = new HashMap<>();
        map.put("status", "0");
        String accessUrl = null;
        try {
            accessUrl = getUrl(kryConfig, "/open/v1/wallet/refundQuery");
        } catch (NoSuchAlgorithmException e) {
            log.error("生成签名异常，请联系管理员!" + e.toString());
            map.put("status", "1");
            map.put("errorMsg", "生成签名异常，请联系管理员!");
            return map;
        }
        Map<String,String> params=new LinkedHashMap<>();
        params.put("outRefundNo",outRefundNo);
        params.put("outTradeNo",outTradeNo);
        try {
            String pushParams = JSONObject.toJSONString(params);
            log.info("退款状态查询请求url:"+accessUrl);
            log.info("退款状态查询请求参数:"+pushParams);
            //发送请求
            String result = HttpsUtil.post(accessUrl, pushParams);
            log.info("退款状态查询返回参数:"+result);
//            JSONObject obj = JSONObject.parseObject(result);
            map.put("resultParams", result);
        } catch (Exception e) {
            log.error("退款状态查询异常，请联系管理员!" + e.toString());
            map.put("status", "1");
            map.put("errorMsg", "退款状态查询异常，请联系管理员!");
            return map;
        }
        return map;
    }


}